/*
 * Copyright (C) 2005 - 2013 MaNGOS <http://www.getmangos.com/>
 *
 * Copyright (C) 2008 - 2013 Trinity <http://www.trinitycore.org/>
 *
 * Copyright (C) 2010 - 2013 ArkCORE <http://www.arkania.net/>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

/// \addtogroup world The World
/// @{
/// \file
#ifndef __WORLD_H
#define __WORLD_H

#include "Common.h"
#include "Timer.h"
#include <ace/Singleton.h>
#include "SharedDefines.h"
#include <ace/Atomic_Op.h>
#include "QueryResult.h"
#include "Callback.h"

#include <map>
#include <set>
#include <list>

class Object;
class WorldPacket;
class WorldSession;
class Player;
struct ScriptInfo;
class WorldSocket;
class SystemMgr;

// ServerMessages.dbc
enum ServerMessageType
{
    SERVER_MSG_SHUTDOWN_TIME = 1, SERVER_MSG_RESTART_TIME = 2, SERVER_MSG_STRING = 3, SERVER_MSG_SHUTDOWN_CANCELLED = 4, SERVER_MSG_RESTART_CANCELLED = 5
};

enum ShutdownMask
{
    SHUTDOWN_MASK_RESTART = 1, SHUTDOWN_MASK_IDLE = 2,
};

enum ShutdownExitCode
{
    SHUTDOWN_EXIT_CODE = 0, ERROR_EXIT_CODE = 1, RESTART_EXIT_CODE = 2,
};

/// Timers for different object refresh rates
enum WorldTimers
{
    WUPDATE_OBJECTS, WUPDATE_SESSIONS, WUPDATE_AUCTIONS, WUPDATE_WEATHERS, WUPDATE_UPTIME, WUPDATE_CORPSES, WUPDATE_EVENTS, WUPDATE_CLEANDB, WUPDATE_AUTOBROADCAST, WUPDATE_MAILBOXQUEUE, WUPDATE_DELETECHARS, WUPDATE_PINGDB, WUPDATE_COUNT
};

/// Configuration elements
enum WorldBoolConfigs
{
    CONFIG_DURABILITY_LOSS_IN_PVP = 0,
    CONFIG_ADDON_CHANNEL,
    CONFIG_ALLOW_PLAYER_COMMANDS,
    CONFIG_CLEAN_CHARACTER_DB,
    CONFIG_GRID_UNLOAD,
    CONFIG_STATS_SAVE_ONLY_ON_LOGOUT,
    CONFIG_ALLOW_TWO_SIDE_ACCOUNTS,
    CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHAT,
    CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL,
    CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP,
    CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD,
    CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION,
    CONFIG_ALLOW_TWO_SIDE_INTERACTION_MAIL,
    CONFIG_ALLOW_TWO_SIDE_WHO_LIST,
    CONFIG_ALLOW_TWO_SIDE_ADD_FRIEND,
    CONFIG_ALLOW_TWO_SIDE_TRADE,
    CONFIG_ALL_TAXI_PATHS,
    CONFIG_INSTANT_TAXI,
    CONFIG_INSTANCE_IGNORE_LEVEL,
    CONFIG_INSTANCE_IGNORE_RAID,
    CONFIG_CAST_UNSTUCK,
    CONFIG_GM_LOG_TRADE,
    CONFIG_ALLOW_GM_GROUP,
    CONFIG_ALLOW_GM_FRIEND,
    CONFIG_GM_LOWER_SECURITY,
    CONFIG_SKILL_PROSPECTING,
    CONFIG_SKILL_MILLING,
    CONFIG_SAVE_RESPAWN_TIME_IMMEDIATELY,
    CONFIG_WEATHER,
    CONFIG_USE_OLD_SKILL_SYSTEM,
    CONFIG_QUEST_IGNORE_RAID,
    CONFIG_DETECT_POS_COLLISION,
    CONFIG_RESTRICTED_LFG_CHANNEL,
    CONFIG_SILENTLY_GM_JOIN_TO_CHANNEL,
    CONFIG_TALENTS_INSPECTING,
    CONFIG_CHAT_FAKE_MESSAGE_PREVENTING,
    CONFIG_DEATH_CORPSE_RECLAIM_DELAY_PVP,
    CONFIG_DEATH_CORPSE_RECLAIM_DELAY_PVE,
    CONFIG_DEATH_BONES_WORLD,
    CONFIG_DEATH_BONES_BG_OR_ARENA,
    CONFIG_DIE_COMMAND_MODE,
    CONFIG_DECLINED_NAMES_USED,
    CONFIG_BATTLEGROUND_CAST_DESERTER,
    CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE,
    CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY,
    CONFIG_BG_XP_FOR_KILL,
    CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS,
    CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE,
    CONFIG_ARENA_QUEUE_ANNOUNCER_PLAYERONLY,
    CONFIG_ARENA_SEASON_IN_PROGRESS,
    CONFIG_ARENA_LOG_EXTENDED_INFO,
    CONFIG_OFFHAND_CHECK_AT_SPELL_UNLEARN,
    CONFIG_VMAP_INDOOR_CHECK,
    CONFIG_PET_LOS,
    CONFIG_START_ALL_SPELLS,
    CONFIG_START_ALL_EXPLORED,
    CONFIG_START_ALL_REP,
    CONFIG_ALWAYS_MAXSKILL,
    CONFIG_PVP_TOKEN_ENABLE,
    CONFIG_NO_RESET_TALENT_COST,
    CONFIG_SHOW_KICK_IN_WORLD,
    CONFIG_CHATLOG_CHANNEL,
    CONFIG_CHATLOG_WHISPER,
    CONFIG_CHATLOG_SYSCHAN,
    CONFIG_CHATLOG_PARTY,
    CONFIG_CHATLOG_RAID,
    CONFIG_CHATLOG_GUILD,
    CONFIG_CHATLOG_PUBLIC,
    CONFIG_CHATLOG_ADDON,
    CONFIG_CHATLOG_BGROUND,
    CONFIG_DUNGEON_FINDER_ENABLE,
    CONFIG_AUTOBROADCAST,
    CONFIG_GUILD_ADVANCEMENT_ENABLED,
    CONFIG_ALLOW_TICKETS,
    CONFIG_PRESERVE_CUSTOM_CHANNELS,
    CONFIG_OUTDOORPVP_WINTERGRASP_ENABLED,
    CONFIG_OUTDOORPVP_WINTERGRASP_CUSTOM_HONOR,
    CONFIG_CONFIG_OUTDOORPVP_WINTERGRASP_ANTIFARM_ENABLE,
    CONFIG_DUEL_RESET_ONE,
    CONFIG_DUEL_RESET_TWO,
    CONFIG_DUEL_RESET_COOLDOWN,
    CONFIG_ANTICHEAT_ENABLE,
    CONFIG_LFG_CAST_DESERTER,
    CONFIG_LFG_CAST_COOLDOWN,
    BOOL_CONFIG_VALUE_COUNT
};

enum WorldFloatConfigs
{
    CONFIG_GROUP_XP_DISTANCE = 0, CONFIG_MAX_RECRUIT_A_FRIEND_DISTANCE, CONFIG_SIGHT_MONSTER, CONFIG_SIGHT_GUARDER, CONFIG_LISTEN_RANGE_SAY, CONFIG_LISTEN_RANGE_TEXTEMOTE, CONFIG_LISTEN_RANGE_YELL, CONFIG_CREATURE_FAMILY_FLEE_ASSISTANCE_RADIUS, CONFIG_CREATURE_FAMILY_ASSISTANCE_RADIUS, CONFIG_THREAT_RADIUS, CONFIG_CHANCE_OF_GM_SURVEY, FLOAT_CONFIG_VALUE_COUNT
};

enum WorldIntConfigs
{
    CONFIG_COMPRESSION = 0, CONFIG_INTERVAL_SAVE, CONFIG_INTERVAL_GRIDCLEAN, CONFIG_INTERVAL_MAPUPDATE, CONFIG_INTERVAL_CHANGEWEATHER, CONFIG_INTERVAL_DISCONNECT_TOLERANCE, CONFIG_PORT_WORLD, CONFIG_SOCKET_TIMEOUTTIME, CONFIG_SESSION_ADD_DELAY, CONFIG_GAME_TYPE, CONFIG_REALM_ZONE, CONFIG_STRICT_PLAYER_NAMES, CONFIG_STRICT_CHARTER_NAMES, CONFIG_STRICT_PET_NAMES, CONFIG_MIN_PLAYER_NAME, CONFIG_MIN_CHARTER_NAME, CONFIG_MIN_PET_NAME, CONFIG_CHARACTER_CREATING_DISABLED, CONFIG_CHARACTER_CREATING_DISABLED_RACEMASK, CONFIG_CHARACTER_CREATING_DISABLED_CLASSMASK, CONFIG_CHARACTERS_PER_ACCOUNT, CONFIG_CHARACTERS_PER_REALM, CONFIG_HEROIC_CHARACTERS_PER_REALM, CONFIG_CHARACTER_CREATING_MIN_LEVEL_FOR_HEROIC_CHARACTER, CONFIG_SKIP_CINEMATICS, CONFIG_MAX_PLAYER_LEVEL, CONFIG_MIN_DUALSPEC_LEVEL, CONFIG_START_PLAYER_LEVEL, CONFIG_START_HEROIC_PLAYER_LEVEL, CONFIG_START_PLAYER_MONEY, CONFIG_MAX_CONQUEST_POINTS, CONFIG_START_CONQUEST_POINTS, CONFIG_MAX_HONOR_POINTS, CONFIG_START_HONOR_POINTS, CONFIG_MAX_JUSTICE_POINTS, CONFIG_START_JUSTICE_POINTS, CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL, CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL_DIFFERENCE, CONFIG_INSTANCE_RESET_TIME_HOUR, CONFIG_INSTANCE_UNLOAD_DELAY, CONFIG_MAX_PRIMARY_TRADE_SKILL, CONFIG_MIN_PETITION_SIGNS, CONFIG_GM_DEV_TAG_ENABLE, CONFIG_GM_DEV_TAG_LEVEL, CONFIG_GM_LOGIN_STATE, CONFIG_GM_VISIBLE_STATE, CONFIG_GM_ACCEPT_TICKETS, CONFIG_GM_CHAT, CONFIG_GM_WHISPERING_TO, CONFIG_GM_LEVEL_IN_GM_LIST, CONFIG_GM_LEVEL_IN_WHO_LIST, CONFIG_GM_LEVEL_ALLOW_ACHIEVEMENTS, CONFIG_START_GM_LEVEL, CONFIG_GROUP_VISIBILITY, CONFIG_MAIL_DELIVERY_DELAY, CONFIG_UPTIME_UPDATE, CONFIG_SKILL_CHANCE_ORANGE, CONFIG_SKILL_CHANCE_YELLOW, CONFIG_SKILL_CHANCE_GREEN, CONFIG_SKILL_CHANCE_GREY, CONFIG_SKILL_CHANCE_MINING_STEPS, CONFIG_SKILL_CHANCE_SKINNING_STEPS, CONFIG_SKILL_GAIN_CRAFTING, CONFIG_SKILL_GAIN_DEFENSE, CONFIG_SKILL_GAIN_GATHERING, CONFIG_SKILL_GAIN_WEAPON, CONFIG_MAX_OVERSPEED_PINGS, CONFIG_EXPANSION, CONFIG_CHATFLOOD_MESSAGE_COUNT, CONFIG_CHATFLOOD_MESSAGE_DELAY, CONFIG_CHATFLOOD_MUTE_TIME, CONFIG_EVENT_ANNOUNCE, CONFIG_CREATURE_FAMILY_ASSISTANCE_DELAY, CONFIG_CREATURE_FAMILY_FLEE_DELAY, CONFIG_WORLD_BOSS_LEVEL_DIFF, CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF, CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF, CONFIG_CHAT_STRICT_LINK_CHECKING_SEVERITY, CONFIG_CHAT_STRICT_LINK_CHECKING_KICK, CONFIG_CHAT_CHANNEL_LEVEL_REQ, CONFIG_CHAT_WHISPER_LEVEL_REQ, CONFIG_CHAT_SAY_LEVEL_REQ, CONFIG_TRADE_LEVEL_REQ, CONFIG_TICKET_LEVEL_REQ, CONFIG_AUCTION_LEVEL_REQ, CONFIG_MAIL_LEVEL_REQ, CONFIG_CORPSE_DECAY_NORMAL, CONFIG_CORPSE_DECAY_RARE, CONFIG_CORPSE_DECAY_ELITE, CONFIG_CORPSE_DECAY_RAREELITE, CONFIG_CORPSE_DECAY_WORLDBOSS, CONFIG_DEATH_SICKNESS_LEVEL, CONFIG_INSTANT_LOGOUT, CONFIG_DISABLE_BREATHING, CONFIG_BATTLEGROUND_INVITATION_TYPE, CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER, CONFIG_BATTLEGROUND_PREMADE_GROUP_WAIT_FOR_MATCH, CONFIG_ARENA_MAX_RATING_DIFFERENCE, CONFIG_ARENA_RATING_DISCARD_TIMER, CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS, CONFIG_ARENA_SEASON_ID, CONFIG_ARENA_START_RATING, CONFIG_ARENA_START_PERSONAL_RATING, CONFIG_ARENA_START_MATCHMAKER_RATING, CONFIG_ARENA_CONQUEST_POINTS_REWARD, CONFIG_MAX_WHO, CONFIG_HONOR_AFTER_DUEL, CONFIG_PVP_TOKEN_MAP_TYPE, CONFIG_PVP_TOKEN_ID, CONFIG_PVP_TOKEN_COUNT, CONFIG_INTERVAL_LOG_UPDATE, CONFIG_MIN_LOG_UPDATE, CONFIG_PLAYER_ALLOW_COMMANDS, CONFIG_NUMTHREADS, CONFIG_ENABLE_SINFO_LOGIN, CONFIG_LOGDB_CLEARINTERVAL, CONFIG_LOGDB_CLEARTIME, CONFIG_CLIENTCACHE_VERSION, CONFIG_GUILD_EVENT_LOG_COUNT, CONFIG_GUILD_BANK_EVENT_LOG_COUNT, CONFIG_MIN_LEVEL_STAT_SAVE, CONFIG_RANDOM_BG_RESET_HOUR, CONFIG_CHARDELETE_KEEP_DAYS, CONFIG_CHARDELETE_METHOD, CONFIG_CHARDELETE_MIN_LEVEL, CONFIG_OUTDOORPVP_WINTERGRASP_START_TIME, CONFIG_OUTDOORPVP_WINTERGRASP_BATTLE_TIME, CONFIG_OUTDOORPVP_WINTERGRASP_INTERVAL, CONFIG_OUTDOORPVP_WINTERGRASP_WIN_BATTLE, CONFIG_OUTDOORPVP_WINTERGRASP_LOSE_BATTLE, CONFIG_OUTDOORPVP_WINTERGRASP_DAMAGED_TOWER, CONFIG_OUTDOORPVP_WINTERGRASP_DESTROYED_TOWER, CONFIG_OUTDOORPVP_WINTERGRASP_DAMAGED_BUILDING, CONFIG_OUTDOORPVP_WINTERGRASP_INTACT_BUILDING, CONFIG_OUTDOORPVP_WINTERGRASP_SAVESTATE_PERIOD, CONFIG_CONFIG_OUTDOORPVP_WINTERGRASP_ANTIFARM_ATK, CONFIG_CONFIG_OUTDOORPVP_WINTERGRASP_ANTIFARM_DEF, CONFIG_AUTOBROADCAST_CENTER, CONFIG_AUTOBROADCAST_INTERVAL, CONFIG_MAX_RESULTS_LOOKUP_COMMANDS, CONFIG_DB_PING_INTERVAL, CONFIG_PRESERVE_CUSTOM_CHANNEL_DURATION, CONFIG_PERSISTENT_CHARACTER_CLEAN_FLAGS, CONFIG_MAX_INSTANCES_PER_HOUR, CONFIG_GUILD_ADVANCEMENT_MAX_LEVEL, CONFIG_IGNORING_MAPS_VERSION, CONFIG_ANTICHEAT_REPORTS_INGAME_NOTIFICATION, INT_CONFIG_VALUE_COUNT
};

/// Server rates
enum Rates
{
    RATE_HEALTH = 0, RATE_POWER_MANA, RATE_POWER_RAGE_INCOME, RATE_POWER_RAGE_LOSS, RATE_POWER_RUNICPOWER_INCOME, RATE_POWER_RUNICPOWER_LOSS, RATE_POWER_FOCUS, RATE_POWER_ENERGY, RATE_SKILL_DISCOVERY, RATE_DROP_ITEM_POOR, RATE_DROP_ITEM_NORMAL, RATE_DROP_ITEM_UNCOMMON, RATE_DROP_ITEM_RARE, RATE_DROP_ITEM_EPIC, RATE_DROP_ITEM_LEGENDARY, RATE_DROP_ITEM_ARTIFACT, RATE_DROP_ITEM_REFERENCED, RATE_DROP_ITEM_REFERENCED_AMOUNT, RATE_DROP_MONEY, RATE_XP_KILL, RATE_XP_KILL_PREMIUM, RATE_XP_QUEST, RATE_XP_QUEST_PREMIUM, RATE_XP_EXPLORE, RATE_XP_EXPLORE_PREMIUM, RATE_REPAIRCOST, RATE_REPUTATION_GAIN, RATE_REPUTATION_LOWLEVEL_KILL, RATE_REPUTATION_LOWLEVEL_QUEST, RATE_REPUTATION_RECRUIT_A_FRIEND_BONUS, RATE_CREATURE_NORMAL_HP, RATE_CREATURE_ELITE_ELITE_HP, RATE_CREATURE_ELITE_RAREELITE_HP, RATE_CREATURE_ELITE_WORLDBOSS_HP, RATE_CREATURE_ELITE_RARE_HP, RATE_CREATURE_NORMAL_DAMAGE, RATE_CREATURE_ELITE_ELITE_DAMAGE, RATE_CREATURE_ELITE_RAREELITE_DAMAGE, RATE_CREATURE_ELITE_WORLDBOSS_DAMAGE, RATE_CREATURE_ELITE_RARE_DAMAGE, RATE_CREATURE_NORMAL_SPELLDAMAGE, RATE_CREATURE_ELITE_ELITE_SPELLDAMAGE, RATE_CREATURE_ELITE_RAREELITE_SPELLDAMAGE, RATE_CREATURE_ELITE_WORLDBOSS_SPELLDAMAGE, RATE_CREATURE_ELITE_RARE_SPELLDAMAGE, RATE_CREATURE_AGGRO, RATE_REST_INGAME, RATE_REST_OFFLINE_IN_TAVERN_OR_CITY, RATE_REST_OFFLINE_IN_WILDERNESS, RATE_DAMAGE_FALL, RATE_AUCTION_TIME, RATE_AUCTION_DEPOSIT, RATE_AUCTION_CUT, RATE_HONOR, RATE_CONQUEST_POINTS_WEEK_LIMIT, RATE_MINING_AMOUNT, RATE_MINING_NEXT, RATE_TALENT, RATE_CORPSE_DECAY_LOOTED, RATE_INSTANCE_RESET_TIME, RATE_TARGET_POS_RECALCULATION_RANGE, RATE_DURABILITY_LOSS_ON_DEATH, RATE_DURABILITY_LOSS_DAMAGE, RATE_DURABILITY_LOSS_PARRY, RATE_DURABILITY_LOSS_ABSORB, RATE_DURABILITY_LOSS_BLOCK, RATE_MOVESPEED, MAX_RATES
};

/// Can be used in SMSG_AUTH_RESPONSE packet
enum BillingPlanFlags
{
    SESSION_NONE = 0x00, SESSION_UNUSED = 0x01, SESSION_RECURRING_BILL = 0x02, SESSION_FREE_TRIAL = 0x04, SESSION_IGR = 0x08, SESSION_USAGE = 0x10, SESSION_TIME_MIXTURE = 0x20, SESSION_RESTRICTED = 0x40, SESSION_ENABLE_CAIS = 0x80,
};

/// Type of server, this is values from second column of Cfg_Configs.dbc
enum RealmType
{
    REALM_TYPE_NORMAL = 0, REALM_TYPE_PVP = 1, REALM_TYPE_NORMAL2 = 4, REALM_TYPE_RP = 6, REALM_TYPE_RPPVP = 8, REALM_TYPE_FFA_PVP = 16          // custom, free for all pvp mode like arena PvP in all zones except rest activated places and sanctuaries
                                                                                                                                                 // replaced by REALM_PVP in realm list
};

enum RealmZone
{
    REALM_ZONE_UNKNOWN = 0,          // any language
    REALM_ZONE_DEVELOPMENT = 1,          // any language
    REALM_ZONE_UNITED_STATES = 2,          // extended-Latin
    REALM_ZONE_OCEANIC = 3,          // extended-Latin
    REALM_ZONE_LATIN_AMERICA = 4,          // extended-Latin
    REALM_ZONE_TOURNAMENT_5 = 5,          // basic-Latin at create, any at login
    REALM_ZONE_KOREA = 6,          // East-Asian
    REALM_ZONE_TOURNAMENT_7 = 7,          // basic-Latin at create, any at login
    REALM_ZONE_ENGLISH = 8,          // extended-Latin
    REALM_ZONE_GERMAN = 9,          // extended-Latin
    REALM_ZONE_FRENCH = 10,          // extended-Latin
    REALM_ZONE_SPANISH = 11,          // extended-Latin
    REALM_ZONE_RUSSIAN = 12,          // Cyrillic
    REALM_ZONE_TOURNAMENT_13 = 13,          // basic-Latin at create, any at login
    REALM_ZONE_TAIWAN = 14,          // East-Asian
    REALM_ZONE_TOURNAMENT_15 = 15,          // basic-Latin at create, any at login
    REALM_ZONE_CHINA = 16,          // East-Asian
    REALM_ZONE_CN1 = 17,          // basic-Latin at create, any at login
    REALM_ZONE_CN2 = 18,          // basic-Latin at create, any at login
    REALM_ZONE_CN3 = 19,          // basic-Latin at create, any at login
    REALM_ZONE_CN4 = 20,          // basic-Latin at create, any at login
    REALM_ZONE_CN5 = 21,          // basic-Latin at create, any at login
    REALM_ZONE_CN6 = 22,          // basic-Latin at create, any at login
    REALM_ZONE_CN7 = 23,          // basic-Latin at create, any at login
    REALM_ZONE_CN8 = 24,          // basic-Latin at create, any at login
    REALM_ZONE_TOURNAMENT_25 = 25,          // basic-Latin at create, any at login
    REALM_ZONE_TEST_SERVER = 26,          // any language
    REALM_ZONE_TOURNAMENT_27 = 27,          // basic-Latin at create, any at login
    REALM_ZONE_QA_SERVER = 28,          // any language
    REALM_ZONE_CN9 = 29,          // basic-Latin at create, any at login
    REALM_ZONE_TEST_SERVER_2 = 30,          // any language
    REALM_ZONE_CN10 = 31,          // basic-Latin at create, any at login
    REALM_ZONE_CTC = 32, REALM_ZONE_CNC = 33, REALM_ZONE_CN1_4 = 34,          // basic-Latin at create, any at login
    REALM_ZONE_CN2_6_9 = 35,          // basic-Latin at create, any at login
    REALM_ZONE_CN3_7 = 36,          // basic-Latin at create, any at login
    REALM_ZONE_CN5_8 = 37          // basic-Latin at create, any at login
};

enum WorldStates
{
    WS_WEEKLY_QUEST_RESET_TIME = 20002,          // Next weekly reset time
    WS_BG_DAILY_RESET_TIME = 20003,          // Next daily BG reset time
    WS_CURRENCY_RESET_TIME = 20004          // Next currency week cap reset time
};

// DB scripting commands
enum ScriptCommands
{
    SCRIPT_COMMAND_TALK = 0,          // source/target = Creature, target = any, datalong = talk type (0=say, 1=whisper, 2=yell, 3=emote text, 4=boss emote text), datalong2 & 1 = player talk (instead of creature), dataint = string_id
    SCRIPT_COMMAND_EMOTE = 1,          // source/target = Creature, datalong = emote id, datalong2 = 0: set emote state; > 0: play emote state
    SCRIPT_COMMAND_FIELD_SET = 2,          // source/target = Creature, datalong = field id, datalog2 = value
    SCRIPT_COMMAND_MOVE_TO = 3,          // source/target = Creature, datalong2 = time to reach, x/y/z = destination
    SCRIPT_COMMAND_FLAG_SET = 4,          // source/target = Creature, datalong = field id, datalog2 = bitmask
    SCRIPT_COMMAND_FLAG_REMOVE = 5,          // source/target = Creature, datalong = field id, datalog2 = bitmask
    SCRIPT_COMMAND_TELEPORT_TO = 6,          // source/target = Creature/Player (see datalong2), datalong = map_id, datalong2 = 0: Player; 1: Creature, x/y/z = destination, o = orientation
    SCRIPT_COMMAND_QUEST_EXPLORED = 7,          // target/source = Player, target/source = GO/Creature, datalong = quest id, datalong2 = distance or 0
    SCRIPT_COMMAND_KILL_CREDIT = 8,          // target/source = Player, datalong = creature entry, datalong2 = 0: personal credit, 1: group credit
    SCRIPT_COMMAND_RESPAWN_GAMEOBJECT = 9,          // source = WorldObject (summoner), datalong = GO guid, datalong2 = despawn delay
    SCRIPT_COMMAND_TEMP_SUMMON_CREATURE = 10,          // source = WorldObject (summoner), datalong = creature entry, datalong2 = despawn delay, x/y/z = summon position, o = orientation
    SCRIPT_COMMAND_OPEN_DOOR = 11,          // source = Unit, datalong = GO guid, datalong2 = reset delay (min 15)
    SCRIPT_COMMAND_CLOSE_DOOR = 12,          // source = Unit, datalong = GO guid, datalong2 = reset delay (min 15)
    SCRIPT_COMMAND_ACTIVATE_OBJECT = 13,          // source = Unit, target = GO
    SCRIPT_COMMAND_REMOVE_AURA = 14,          // source (datalong2 != 0) or target (datalong2 == 0) = Unit, datalong = spell id
    SCRIPT_COMMAND_CAST_SPELL = 15,          // source and/or target = Unit, datalong2 = cast direction (0: s->t 1: s->s 2: t->t 3: t->s 4: s->creature with dataint entry), dataint & 1 = triggered flag
    SCRIPT_COMMAND_PLAY_SOUND = 16,          // source = WorldObject, target = none/Player, datalong = sound id, datalong2 (bitmask: 0/1=anyone/player, 0/2=without/with distance dependency, so 1|2 = 3 is target with distance dependency)
    SCRIPT_COMMAND_CREATE_ITEM = 17,          // target/source = Player, datalong = item entry, datalong2 = amount
    SCRIPT_COMMAND_DESPAWN_SELF = 18,          // target/source = Creature, datalong = despawn delay

    SCRIPT_COMMAND_LOAD_PATH = 20,          // source = Unit, datalong = path id, datalong2 = is repeatable
    SCRIPT_COMMAND_CALLSCRIPT_TO_UNIT = 21,          // source = WorldObject (if present used as a search center), datalong = script id, datalong2 = unit lowguid, dataint = script table to use (see ScriptsType)
    SCRIPT_COMMAND_KILL = 22,          // source/target = Creature, dataint = remove corpse attribute

    // TrinityCore only
    SCRIPT_COMMAND_ORIENTATION = 30,          // source = Unit, target (datalong > 0) = Unit, datalong = > 0 turn source to face target, o = orientation
    SCRIPT_COMMAND_EQUIP = 31,          // soucre = Creature, datalong = equipment id
    SCRIPT_COMMAND_MODEL = 32,          // source = Creature, datalong = model id
    SCRIPT_COMMAND_CLOSE_GOSSIP = 33,          // source = Player
    SCRIPT_COMMAND_PLAYMOVIE = 34          // source = Player, datalong = movie id
};

/// Storage class for commands issued for delayed execution
struct CliCommandHolder
{
    typedef void Print (void*, const char*);
    typedef void CommandFinished (void*, bool success);

    void* m_callbackArg;
    char *m_command;
    Print* m_print;

    CommandFinished* m_commandFinished;

    CliCommandHolder (void* callbackArg, const char *command, Print* zprint, CommandFinished* commandFinished) :
            m_callbackArg(callbackArg), m_print(zprint), m_commandFinished(commandFinished)
    {
        size_t len = strlen(command) + 1;
        m_command = new char[len];
        memcpy(m_command, command, len);
    }

    ~CliCommandHolder ()
    {
        delete[] m_command;
    }
};

typedef UNORDERED_MAP<uint32, WorldSession*> SessionMap;

/// The World
class World
{
public:
    static volatile uint32 m_worldLoopCounter;

    World ();
    ~World ();

    WorldSession* FindSession (uint32 id) const;
    void AddSession (WorldSession *s);
    void SendAutoBroadcast ();
    bool RemoveSession (uint32 id);
    /// Get the number of current active sessions
    void UpdateMaxSessionCounters ();
    const SessionMap& GetAllSessions () const
    {
        return m_sessions;
    }
    uint32 GetActiveAndQueuedSessionCount () const
    {
        return m_sessions.size();
    }
    uint32 GetActiveSessionCount () const
    {
        return m_sessions.size() - m_QueuedPlayer.size();
    }
    uint32 GetQueuedSessionCount () const
    {
        return m_QueuedPlayer.size();
    }
    /// Get the maximum number of parallel sessions on the server since last reboot
    uint32 GetMaxQueuedSessionCount () const
    {
        return m_maxQueuedSessionCount;
    }
    uint32 GetMaxActiveSessionCount () const
    {
        return m_maxActiveSessionCount;
    }
    /// Get number of players
    inline uint32 GetPlayerCount () const
    {
        return m_PlayerCount;
    }
    inline uint32 GetMaxPlayerCount () const
    {
        return m_MaxPlayerCount;
    }
    /// Increase/Decrease number of players
    inline void IncreasePlayerCount ()
    {
        m_PlayerCount++;
        m_MaxPlayerCount = std::max(m_MaxPlayerCount, m_PlayerCount);
    }
    inline void DecreasePlayerCount ()
    {
        m_PlayerCount--;
    }

    Player* FindPlayerInZone (uint32 zone);

    /// Deny clients?
    bool IsClosed () const;

    /// Close world
    void SetClosed (bool val);

    /// Security level limitations
    AccountTypes GetPlayerSecurityLimit () const
    {
        return m_allowedSecurityLevel;
    }
    void SetPlayerSecurityLimit (AccountTypes sec);
    void LoadDBAllowedSecurityLevel ();

    /// Active session server limit
    void SetPlayerAmountLimit (uint32 limit)
    {
        m_playerLimit = limit;
    }
    uint32 GetPlayerAmountLimit () const
    {
        return m_playerLimit;
    }

    //player Queue
    typedef std::list<WorldSession*> Queue;
    void AddQueuedPlayer (WorldSession*);
    bool RemoveQueuedPlayer (WorldSession* session);
    int32 GetQueuePos (WorldSession*);
    bool HasRecentlyDisconnected (WorldSession*);

    /// \todo Actions on m_allowMovement still to be implemented
    /// Is movement allowed?
    bool getAllowMovement () const
    {
        return m_allowMovement;
    }
    /// Allow/Disallow object movements
    void SetAllowMovement (bool allow)
    {
        m_allowMovement = allow;
    }

    /// Set a new Message of the Day
    void SetMotd (const std::string& motd);
    /// Get the current Message of the Day
    const char* GetMotd () const;

    /// Set the string for new characters (first login)
    void SetNewCharString (std::string str)
    {
        m_newCharString = str;
    }
    /// Get the string for new characters (first login)
    const std::string& GetNewCharString () const
    {
        return m_newCharString;
    }

    LocaleConstant GetDefaultDbcLocale () const
    {
        return m_defaultDbcLocale;
    }

    /// Get the path where data (dbc, maps) are stored on disk
    std::string GetDataPath () const
    {
        return m_dataPath;
    }

    /// When server started?
    time_t const& GetStartTime () const
    {
        return m_startTime;
    }
    /// What time is it?
    time_t const& GetGameTime () const
    {
        return m_gameTime;
    }
    /// Uptime (in secs)
    uint32 GetUptime () const
    {
        return uint32(m_gameTime - m_startTime);
    }
    /// Update time
    uint32 GetUpdateTime () const
    {
        return m_updateTime;
    }
    void SetRecordDiffInterval (int32 t)
    {
        if (t >= 0)
            m_int_configs[CONFIG_INTERVAL_LOG_UPDATE] = (uint32) t;
    }

    /// Next daily quests and random bg reset time
    time_t GetNextDailyQuestsResetTime () const
    {
        return m_NextDailyQuestReset;
    }
    time_t GetNextWeeklyQuestsResetTime () const
    {
        return m_NextWeeklyQuestReset;
    }
    time_t GetNextRandomBGResetTime () const
    {
        return m_NextRandomBGReset;
    }
    time_t GetNextCurrencyResetTime () const
    {
        return m_NextCurrencyReset;
    }

    /// Get the maximum skill level a player can reach
    uint16 GetConfigMaxSkillValue () const
    {
        uint8 lvl = getIntConfig(CONFIG_MAX_PLAYER_LEVEL);
        return lvl > 60 ? 300 + ((lvl - 60) * 75) / 10 : lvl * 5;
    }

    void SetInitialWorldSettings ();
    void LoadConfigSettings (bool reload = false);

    void SendWorldText (int32 string_id, ...);
    void SendGlobalText (const char* text, WorldSession *self);
    void SendGMText (int32 string_id, ...);
    void SendGlobalMessage (WorldPacket *packet, WorldSession *self = 0, uint32 team = 0);
    void SendGlobalGMMessage (WorldPacket *packet, WorldSession *self = 0, uint32 team = 0);
    void SendZoneMessage (uint32 zone, WorldPacket *packet, WorldSession *self = 0, uint32 team = 0);
    void SendZoneText (uint32 zone, const char *text, WorldSession *self = 0, uint32 team = 0);
    void SendServerMessage (ServerMessageType type, const char *text = "", Player* player = NULL);

    /// Are we in the middle of a shutdown?
    bool IsShutdowning () const
    {
        return m_ShutdownTimer > 0;
    }
    void ShutdownServ (uint32 time, uint32 options, uint8 exitcode);
    void ShutdownCancel ();
    void ShutdownMsg (bool show = false, Player* player = NULL);
    static uint8 GetExitCode ()
    {
        return m_ExitCode;
    }
    static void StopNow (uint8 exitcode)
    {
        m_stopEvent = true;
        m_ExitCode = exitcode;
    }
    static bool IsStopped ()
    {
        return m_stopEvent;
    }

    void Update (uint32 diff);

    void UpdateSessions (uint32 diff);
    /// Set a server rate (see #Rates)
    void setRate (Rates rate, float value)
    {
        rate_values[rate] = value;
    }
    /// Get a server rate (see #Rates)
    float getRate (Rates rate) const
    {
        return rate_values[rate];
    }

    /// Set a server configuration element (see #WorldConfigs)
    void setBoolConfig (WorldBoolConfigs index, bool value)
    {
        if (index < BOOL_CONFIG_VALUE_COUNT)
            m_bool_configs[index] = value;
    }

    /// Get a server configuration element (see #WorldConfigs)
    bool getBoolConfig (WorldBoolConfigs index) const
    {
        return index < BOOL_CONFIG_VALUE_COUNT ? m_bool_configs[index] : 0;
    }

    /// Set a server configuration element (see #WorldConfigs)
    void setFloatConfig (WorldFloatConfigs index, float value)
    {
        if (index < FLOAT_CONFIG_VALUE_COUNT)
            m_float_configs[index] = value;
    }

    /// Get a server configuration element (see #WorldConfigs)
    float getFloatConfig (WorldFloatConfigs index) const
    {
        return index < FLOAT_CONFIG_VALUE_COUNT ? m_float_configs[index] : 0;
    }

    /// Set a server configuration element (see #WorldConfigs)
    void setIntConfig (WorldIntConfigs index, uint32 value)
    {
        if (index < INT_CONFIG_VALUE_COUNT)
            m_int_configs[index] = value;
    }

    /// Get a server configuration element (see #WorldConfigs)
    uint32 getIntConfig (WorldIntConfigs index) const
    {
        return index < INT_CONFIG_VALUE_COUNT ? m_int_configs[index] : 0;
    }

    void setWorldState (uint32 index, uint64 value);
    uint64 getWorldState (uint32 index) const;
    void LoadWorldStates ();

    /// Are we on a "Player versus Player" server?
    bool IsPvPRealm ()
    {
        return (getIntConfig(CONFIG_GAME_TYPE) == REALM_TYPE_PVP || getIntConfig(CONFIG_GAME_TYPE) == REALM_TYPE_RPPVP || getIntConfig(CONFIG_GAME_TYPE) == REALM_TYPE_FFA_PVP);
    }
    bool IsFFAPvPRealm ()
    {
        return getIntConfig(CONFIG_GAME_TYPE) == REALM_TYPE_FFA_PVP;
    }

    void KickAll ();
    void KickAllLess (AccountTypes sec);
    BanReturn BanAccount (BanMode mode, std::string nameOrIP, std::string duration, std::string reason, std::string author);
    bool RemoveBanAccount (BanMode mode, std::string nameOrIP);
    BanReturn BanCharacter (std::string name, std::string duration, std::string reason, std::string author);
    bool RemoveBanCharacter (std::string name);

    uint32 IncreaseScheduledScriptsCount ()
    {
        return (uint32) ++m_scheduledScripts;
    }
    uint32 DecreaseScheduledScriptCount ()
    {
        return (uint32) --m_scheduledScripts;
    }
    uint32 DecreaseScheduledScriptCount (size_t count)
    {
        return (uint32) (m_scheduledScripts -= count);
    }
    bool IsScriptScheduled () const
    {
        return m_scheduledScripts > 0;
    }

    // for max speed access
    static float GetMaxVisibleDistanceOnContinents ()
    {
        return m_MaxVisibleDistanceOnContinents;
    }
    static float GetMaxVisibleDistanceInInstances ()
    {
        return m_MaxVisibleDistanceInInstances;
    }
    static float GetMaxVisibleDistanceInBGArenas ()
    {
        return m_MaxVisibleDistanceInBGArenas;
    }

    static int32 GetVisibilityNotifyPeriodOnContinents ()
    {
        return m_visibility_notify_periodOnContinents;
    }
    static int32 GetVisibilityNotifyPeriodInInstances ()
    {
        return m_visibility_notify_periodInInstances;
    }
    static int32 GetVisibilityNotifyPeriodInBGArenas ()
    {
        return m_visibility_notify_periodInBGArenas;
    }

    void ProcessCliCommands ();
    void QueueCliCommand (CliCommandHolder* commandHolder)
    {
        cliCmdQueue.add(commandHolder);
    }

    void ForceGameEventUpdate ();

    void UpdateRealmCharCount (uint32 accid);

    LocaleConstant GetAvailableDbcLocale (LocaleConstant locale) const
    {
        if (m_availableDbcLocaleMask & (1 << locale))
            return locale;
        else
            return m_defaultDbcLocale;
    }

    //used World DB version
    void LoadDBVersion ();
    char const* GetDBVersion () const
    {
        return m_DBVersion.c_str();
    }
    char const* GetCreatureAIVersion () const
    {
        return m_CreatureAIVersion.c_str();
    }

    void RecordTimeDiff (const char * text, ...);

    void LoadAutobroadcasts ();

    void UpdateAreaDependentAuras ();

    uint32 debugOpcode;

    void ProcessStartEvent ();
    void ProcessStopEvent ();
    bool GetEventKill () const
    {
        return isEventKillStart;
    }

    bool isEventKillStart;

    // Wintergrasp
    uint32 GetWintergrapsTimer ()
    {
        return m_WintergrapsTimer;
    }
    uint32 GetWintergrapsState ()
    {
        return m_WintergrapsState;
    }
    uint32 m_WintergrapsTimer;
    uint32 m_WintergrapsState;
    void SendWintergraspState ();
    void SetWintergrapsTimer (uint32 timer, uint32 state)
    {
        m_WintergrapsTimer = timer;
        m_WintergrapsState = state;
    }

    uint32 GetCleaningFlags ()
    {
        return m_CleaningFlags;
    }
    void SetCleaningFlags (uint32 flags)
    {
        m_CleaningFlags = flags;
    }
    std::string AntiCheatWarnChannel;
protected:
    void _UpdateGameTime ();
    // callback for UpdateRealmCharacters
    void _UpdateRealmCharCount (QueryResult resultCharCount, uint32 accountId);

    void InitDailyQuestResetTime ();
    void InitWeeklyQuestResetTime ();
    void InitRandomBGResetTime ();
    void InitCurrencyResetTime ();
    void ResetDailyQuests ();
    void ResetWeeklyQuests ();
    void ResetRandomBG ();
    void ResetCurrencyWeekCap ();
private:
    static volatile bool m_stopEvent;
    static uint8 m_ExitCode;
    uint32 m_ShutdownTimer;
    uint32 m_ShutdownMask;

    uint32 m_CleaningFlags;

    bool m_isClosed;

    //atomic op counter for active scripts amount
    ACE_Atomic_Op<ACE_Thread_Mutex, long> m_scheduledScripts;

    time_t m_startTime;
    time_t m_gameTime;
    IntervalTimer m_timers[WUPDATE_COUNT];
    time_t mail_timer;
    time_t mail_timer_expires;
    uint32 m_updateTime, m_updateTimeSum;
    uint32 m_updateTimeCount;
    uint32 m_currentTime;

    //typedef UNORDERED_MAP<uint32, WorldSession*> SessionMap;
    SessionMap m_sessions;
    typedef UNORDERED_MAP<uint32, time_t> DisconnectMap;
    DisconnectMap m_disconnects;
    uint32 m_maxActiveSessionCount;
    uint32 m_maxQueuedSessionCount;
    uint32 m_PlayerCount;
    uint32 m_MaxPlayerCount;

    std::string m_newCharString;

    float rate_values[MAX_RATES];
    uint32 m_int_configs[INT_CONFIG_VALUE_COUNT];
    bool m_bool_configs[BOOL_CONFIG_VALUE_COUNT];
    float m_float_configs[FLOAT_CONFIG_VALUE_COUNT];
    typedef std::map<uint32, uint64> WorldStatesMap;
    WorldStatesMap m_worldstates;
    uint32 m_playerLimit;
    AccountTypes m_allowedSecurityLevel;
    LocaleConstant m_defaultDbcLocale;          // from config for one from loaded DBC locales
    uint32 m_availableDbcLocaleMask;// by loaded DBC
    void DetectDBCLang();
    bool m_allowMovement;
    std::string m_motd;
    std::string m_dataPath;

    // for max speed access
    static float m_MaxVisibleDistanceOnContinents;
    static float m_MaxVisibleDistanceInInstances;
    static float m_MaxVisibleDistanceInBGArenas;

    static int32 m_visibility_notify_periodOnContinents;
    static int32 m_visibility_notify_periodInInstances;
    static int32 m_visibility_notify_periodInBGArenas;

    // CLI command holder to be thread safe
    ACE_Based::LockedQueue<CliCommandHolder*, ACE_Thread_Mutex> cliCmdQueue;

    // next daily quests and random bg reset time
    time_t m_NextDailyQuestReset;
    time_t m_NextWeeklyQuestReset;
    time_t m_NextRandomBGReset;
    time_t m_NextCurrencyReset;

    //Player Queue
    Queue m_QueuedPlayer;

    //sessions that are added async
    void AddSession_(WorldSession* s);
    ACE_Based::LockedQueue<WorldSession*, ACE_Thread_Mutex> addSessQueue;

    //used versions
    std::string m_DBVersion;
    std::string m_CreatureAIVersion;
    std::list<std::string> m_Autobroadcasts;

private:
    void ProcessQueryCallbacks();
    QueryCallback<QueryResult, uint32> m_realmCharCallback;
};

extern uint32 realmID;

#define sWorld ACE_Singleton<World, ACE_Null_Mutex>::instance()
#endif
/// @}
